<?php

Raise::load('core.RaiseObject');
Raise::load('core.IRaiseComparable');
Raise::load('core.RaiseInvalidRequestException');
Raise::load('core.RaiseDateTime');

/**
 * RaiseTimer class
 * for calculating time between start and stop
 *
 * @author Sam-Mauris Yong <hellclanner at live dot com>
 * @license http://www.opensource.org/licenses/bsd-license New BSD License
 * @package Raise.Core.DateTime
 * @since 1.2
 */
class RaiseTimer extends RaiseObject implements IRaiseComparable {

    /**
     * The start time of the timer
     * @var integer|double
     */
    private $startTime = false;

    /**
     * The end time of the timer
     * @var integer|double
     */
    private $endTime = false;

    /**
     * Creates a new timer
     * @param boolean $start Set whether to start or don't start the timer upon creation (optional, default FALSE).
     */
    function __construct($start = false){
        if($start){
            $this->start();
        }
    }

    /**
     * Start the timer
     */
    public function start(){
        if($this->isRunning()){
            throw new RaiseInvalidRequestException('Timer is already running. start() cannot be called when the Timer is running.');
            return;
        }
        $this->startTime = RaiseDateTime::getMicrotime();
    }

    /**
     * Stop the timer
     * @return double|integer the result of the timing
     */
    public function stop(){
        if(!$this->isRunning()){
            throw new RaiseInvalidRequestException('Timer cannot be stopped if it is not started in the first place.');
            return;
        }
        $this->endTime = RaiseDateTime::getMicrotime();
        return $this->result();
    }

    /**
     * Gets the result of the timing
     * @return double|integer
     */
    public function result(){
        return $this->endTime - $this->startTime;
    }

    /**
     * Resets the timer
     */
    public function reset(){
        $this->startTime = false;
        $this->endTime = false;
    }

    /**
     * Checks if the timer is running or not
     * @return boolean TRUE if the timer is running, FALSE otherwise.
     */
    public function isRunning(){
        if($this->startTime && !$this->endTime){
            return true;
        }
        return false;
    }

    /**
     * Compare to another RaiseTimer
     * @param RaiseTimer $o2
     * @return double|integer
     */
    public function compareTo($o2) {
        if($this->isRunning() || $o2->isRunning()){
            throw new RaiseInvalidRequestException('When comparing two RaiseTimers, both RaiseTimers must not be running.');
        }
        return $o2->result() - $this->result();
    }

}

